/**
 * 
 */
package edu.gatech.cs3240.NFA;

import java.util.ArrayList;
import java.util.Hashtable;

import edu.gatech.cs3240.Token;

/**
 * Represents an individual state in an NFA.
 * @author VRamachandran
 */
public class State { 

	private String name;
	private boolean accepting;
	private ArrayList<Transition> paths;
	
	public State(String name, boolean accept, ArrayList<Transition> paths) {
		this.name = name;
		this.accepting = accept;
		this.paths = paths;
	}
	
	public State(String name, boolean accept) {
		this(name, accept, new ArrayList<Transition>());
	}
	
	public State(boolean accept) {
		this("X", accept);
	}
	
	public void addTransition(State destination, Token consume) {
		Transition t = new Transition(this, destination, consume);
		if(!paths.contains(t))
			paths.add(t);
	}
	
	public void addTransition(State destination) {
		Transition t = new Transition(this, destination);
		if(!paths.contains(t))
			paths.add(t);
	}
	
	/**
	 * Is this an accepting state?
	 * @return
	 */
	public boolean isAccepting() {
		return accepting;
	}
	
	/**
	 * Get the set of possible transitions leading out of this State.
	 * @return
	 */
	public ArrayList<Transition> getPaths() {
		return paths;
	}
	
	public String getName() {
		return name;
	}
	
	public void setAccepting(boolean a) {
		accepting = a;
	}
	
	/**
	 * @see edu.gatech.cs3240.NFA.NFA.toString().
	 */
	public String toString(String prefix, Hashtable<State, Integer> used) {
		if(used.get(this) != null) {
			// This state has already been expanded in the tree, don't bother 
			// expanding again (to avoid an infinite loop).
			if(accepting)
				return "<{" + used.get(this) + "}>\n";
			else
				return "<" + used.get(this) + ">\n";
		} else {
			// The state hasn't been expanded in the output string yet; add it.
			String s;
			if(accepting) {
				s = "<{" + used.size() + "}>\n";
			} else {
				s = "<" + used.size() + ">\n";
			}
			used.put(this, used.size());
			for(int j = 0; j < paths.size(); j++) {
				if(paths.get(j).isEpsilon())
					s += prefix + "-E-" + "\t";
				else 
					s += prefix + "-" 
						+ paths.get(j).getConsumable().toString() + "-" + "\t";
				s += paths.get(j).getTarget().toString(prefix + "\t", used);
			}
			return s;
		}
	}
}